/**
 * File: War3Source_TrollBatRider.sp
 * Description: The Troll Bat Rider race for War3Source.
 * Author(s): [Oddity]TeacherCreature & Frenzzy
 */

#pragma semicolon 1

#include <sourcemod>
#include "W3SIncs/War3Source_Interface"
#include <cstrike>

new thisRaceID;
new SKILL_REGEN, SKILL_ARCANITE, SKILL_LIQUIDFIRE, ULT_CONCOCTION;

// Race Model
new String:g_szRaceModelT[PLATFORM_MAX_PATH] = "models/player/techknow/demon/demon.mdl";
new String:g_szRaceModelCT[PLATFORM_MAX_PATH] = "models/player/techknow/demon/demon_ct.mdl";
new Handle:g_hCvarCustomModel = INVALID_HANDLE;
new bool:g_bCustomModel = true;

// Skill 1
new RegenAmountArr[6] = {0, 1, 2, 3, 4, 5};

// Skill 2
new Float:ArcaniteDamagePercent[6] = {1.0, 1.25, 1.3, 1.35, 1.4, 1.45};
new Float:ArcaniteChance[6] = {0.0, 0.48, 0.56, 0.64, 0.74, 0.8};

// Skill 3
new Float:LiquidFireArr[6] = {1.0, 2.0, 3.0, 4.0, 5.0, 6.0};

// Ultimate
new Handle:g_hCvarUltCooldown = INVALID_HANDLE;
new Handle:g_hCvarFlyingType = INVALID_HANDLE;
new Float:g_fUltCooldown = 0.0;
new bool:g_bFlyingType = true;
new bool:g_bFlying[MAXPLAYERS + 1];

// Other
new g_iOffsetAmmo = -1;
new Handle:g_hCvarAmountOfGrenades = INVALID_HANDLE;
new g_iAmountOfGrenades = 115;

public Plugin:myinfo = {
	name = "War3Source Race - Troll Bat Rider",
	author = "[Oddity]TeacherCreature & Frenzzy",
	description = "The Troll Bat Rider race for War3Source",
	version = "2.0",
	url = "www.war3source.com"
};

public OnMapStart()
{
	if (g_bCustomModel && FileExists(g_szRaceModelT) && FileExists(g_szRaceModelCT))
	{
		AddFileToDownloadsTable(g_szRaceModelT);
		AddFileToDownloadsTable(g_szRaceModelCT);
		AddFileToDownloadsTable("materials/models/player/techknow/demon/demon.vmt");
		AddFileToDownloadsTable("materials/models/player/techknow/demon/demon.vtf");
		AddFileToDownloadsTable("materials/models/player/techknow/demon/demon_ct.vmt");
		AddFileToDownloadsTable("materials/models/player/techknow/demon/demon_ct.vtf");
		AddFileToDownloadsTable("materials/models/player/techknow/demon/demon_n.vtf");
		AddFileToDownloadsTable("materials/models/player/techknow/demon/eyes.vmt");
		AddFileToDownloadsTable("materials/models/player/techknow/demon/eyes.vtf");
		AddFileToDownloadsTable("materials/models/player/techknow/demon/w-h.vmt");
		AddFileToDownloadsTable("materials/models/player/techknow/demon/w-h.vtf");
		AddFileToDownloadsTable("materials/models/player/techknow/demon/w-h_ct.vmt");
		AddFileToDownloadsTable("materials/models/player/techknow/demon/w-h_ct.vtf");
		AddFileToDownloadsTable("materials/models/player/techknow/demon/w-h_n.vtf");
		
		AddFileToDownloadsTable("models/player/techknow/demon/demon.dx80.vtx");
		AddFileToDownloadsTable("models/player/techknow/demon/demon.dx90.vtx");
		AddFileToDownloadsTable("models/player/techknow/demon/demon.phy");
		AddFileToDownloadsTable("models/player/techknow/demon/demon.sw.vtx");
		AddFileToDownloadsTable("models/player/techknow/demon/demon.vvd");
		AddFileToDownloadsTable("models/player/techknow/demon/demon_ct.dx80.vtx");
		AddFileToDownloadsTable("models/player/techknow/demon/demon_ct.dx90.vtx");
		AddFileToDownloadsTable("models/player/techknow/demon/demon_ct.phy");
		AddFileToDownloadsTable("models/player/techknow/demon/demon_ct.sw.vtx");
		AddFileToDownloadsTable("models/player/techknow/demon/demon_ct.vvd");
		PrecacheModel(g_szRaceModelT, true);
		PrecacheModel(g_szRaceModelCT, true);
	}
}

public OnPluginStart()
{
	LoadTranslations("w3s.race.tbr.phrases");
	
	g_iOffsetAmmo = FindSendPropOffs("CCSPlayer", "m_iAmmo");
	
	HookEvent("weapon_fire", Event_WeaponFire);
	
	g_hCvarUltCooldown = CreateConVar("war3_tbr_flying_cooldown", "0.0", "Cooldown for Flying");
	g_hCvarFlyingType = CreateConVar("war3_tbr_flying_type", "1", "Enable/Disable hold key for Flying");
	g_hCvarCustomModel = CreateConVar("war3_tbr_custom_model", "1", "Enable/Disable custom model");
	g_hCvarAmountOfGrenades = CreateConVar("war3_tbr_grenades", "115", "Amount of grenades");
	
	HookConVarChange(g_hCvarUltCooldown, OnConVarChange);
	HookConVarChange(g_hCvarFlyingType, OnConVarChange);
	HookConVarChange(g_hCvarCustomModel, OnConVarChange);
	HookConVarChange(g_hCvarAmountOfGrenades, OnConVarChange);
	
	CreateTimer(1.0, CalcRegenWaves, _, TIMER_REPEAT);
}

public OnWar3PluginReady()
{
	thisRaceID       = War3_CreateNewRaceT("tbr");
	SKILL_REGEN      = War3_AddRaceSkillT(thisRaceID, "Regenerate", false, 5);
	SKILL_ARCANITE   = War3_AddRaceSkillT(thisRaceID, "Arcanite", false, 5);
	SKILL_LIQUIDFIRE = War3_AddRaceSkillT(thisRaceID, "LiquidFire", false, 5);
	ULT_CONCOCTION   = War3_AddRaceSkillT(thisRaceID, "BatRider", true, 1); 
	War3_CreateRaceEnd(thisRaceID);
}

public OnRaceChanged(client,oldrace,newrace)
{
	if (newrace != thisRaceID)
	{
		g_bFlying[client] = false;
		War3_SetBuff(client, bFlyMode, thisRaceID, false);
		War3_WeaponRestrictTo(client, thisRaceID, "");
	}
	else
	{
		g_bFlying[client] = false;
		War3_SetBuff(client, bFlyMode, thisRaceID, false);
		War3_WeaponRestrictTo(client, thisRaceID, "weapon_knife,weapon_hegrenade");
		
		if (IsPlayerAlive(client))
		{
			if (g_bCustomModel)
			{
				if (IsModelPrecached(g_szRaceModelT) && GetClientTeam(client) == CS_TEAM_T)
					SetEntityModel(client, g_szRaceModelT);
				else if (IsModelPrecached(g_szRaceModelCT) && GetClientTeam(client) == CS_TEAM_CT)
					SetEntityModel(client, g_szRaceModelCT);
			}
			
			new iWeapon;
			iWeapon = GetPlayerWeaponSlot(client, CS_SLOT_PRIMARY);
			if (iWeapon != -1)
				RemovePlayerItem(client, iWeapon);
			iWeapon = GetPlayerWeaponSlot(client, CS_SLOT_SECONDARY);
			if (iWeapon != -1)
				RemovePlayerItem(client, iWeapon);
			do
			{
				iWeapon = GetPlayerWeaponSlot(client, CS_SLOT_GRENADE);
				if (iWeapon != -1)
					RemovePlayerItem(client, iWeapon);
			}
			while (iWeapon != -1);
			
			iWeapon = GivePlayerItem(client, "weapon_hegrenade");
			if ((iWeapon != -1) && IsValidEntity(iWeapon))
			{
				SetEntData(client, g_iOffsetAmmo + (11 * 4), g_iAmountOfGrenades);
				FakeClientCommand(client, "use weapon_hegrenade");
			}
			else
			{
				FakeClientCommand(client, "use weapon_knife");
			}
		}
	}
}

public OnWar3EventSpawn(client)
{
	ExtinguishEntity(client);
	if (War3_GetRace(client) == thisRaceID)
	{
		g_bFlying[client] = false;
		War3_SetBuff(client, bFlyMode, thisRaceID, false);
		
		if (g_bCustomModel)
		{
			if (IsModelPrecached(g_szRaceModelT) && GetClientTeam(client) == CS_TEAM_T)
				SetEntityModel(client, g_szRaceModelT);
			else if (IsModelPrecached(g_szRaceModelCT) && GetClientTeam(client) == CS_TEAM_CT)
				SetEntityModel(client, g_szRaceModelCT);
		}
		
		new iWeapon = GivePlayerItem(client, "weapon_hegrenade");
		if ((iWeapon != -1) && IsValidEntity(iWeapon))
		{
			SetEntData(client, g_iOffsetAmmo + (11 * 4), g_iAmountOfGrenades);
			FakeClientCommand(client, "use weapon_hegrenade");
		}
		else
		{
			FakeClientCommand(client, "use weapon_knife");
		}
	}
}

public Action:Event_WeaponFire(Handle:event, const String:name[], bool:dontBroadcast)
{
	new userid = GetEventInt(event, "userid");
	new client = GetClientOfUserId(userid);
	if (War3_GetRace(client) == thisRaceID)
	{
		decl String:weapon[64];
		GetEventString(event, "weapon", weapon, sizeof(weapon));
		if (StrContains(weapon, "hegrenade", false) != -1)
		{
			CreateTimer(0.8, UseGrenade, client);
		}
	}
}

public Action:UseGrenade(Handle:timer, any:client)
{
	if (ValidPlayer(client, true))
	{
		if (War3_GetRace(client) == thisRaceID)
		{
			new ammo = GetEntData(client, g_iOffsetAmmo + (11 * 4));
			if (ammo > 0)
			{
				FakeClientCommand(client, "use weapon_hegrenade");
			}
		}
	}
}

public Action:CalcRegenWaves(Handle:timer, any:data)
{
	for (new i = 1; i <= MaxClients; i++)
	{
		if (IsClientInGame(i) && IsPlayerAlive(i))
		{
			if (War3_GetRace(i) == thisRaceID)
			{
				new regen_hp = RegenAmountArr[War3_GetSkillLevel(i, thisRaceID, SKILL_REGEN)];
				if (regen_hp > 0)
				{
					War3_HealToMaxHP(i, regen_hp);
				}
			}
		}
	}
}

public OnW3TakeDmgBulletPre(victim, attacker, Float:damage)
{
	if (ValidPlayer(victim) && ValidPlayer(attacker) && GetClientTeam(victim) != GetClientTeam(attacker))
	{
		if (War3_GetRace(attacker) == thisRaceID && !W3HasImmunity(victim, Immunity_Skills))
		{
			new arcanite = War3_GetSkillLevel(attacker, thisRaceID, SKILL_ARCANITE);
			new liquidfire = War3_GetSkillLevel(attacker, thisRaceID, SKILL_LIQUIDFIRE);
			if (arcanite > 0 && War3_Chance(ArcaniteChance[arcanite]))
			{
				War3_DamageModPercent(ArcaniteDamagePercent[arcanite]);
				PrintToConsole(attacker, "%t", "You did {amount} extra damage to {player} with Arcanite", RoundToFloor(damage * ArcaniteDamagePercent[arcanite] - damage), victim);
				W3FlashScreen(victim, RGBA_COLOR_RED);
			}
			if (liquidfire > 0 && War3_Chance(0.5))
			{
				IgniteEntity(victim, LiquidFireArr[liquidfire]);
				PrintToConsole(attacker, "%t", "Liquid Fire burns your enemy");
				W3FlashScreen(victim, RGBA_COLOR_RED);
			}
		}
	}
}

public OnWar3EventDeath(victim, attacker)
{
	ExtinguishEntity(victim);
}

public OnUltimateCommand(client, race, bool:pressed)
{
	if (race == thisRaceID && IsPlayerAlive(client))
	{
		if (pressed)
		{
			if (War3_GetSkillLevel(client, thisRaceID, ULT_CONCOCTION) > 0)
			{
				if (War3_SkillNotInCooldown(client, thisRaceID, ULT_CONCOCTION, false))
				{
					if (!Silenced(client))
					{
						if (g_bFlyingType)
						{
							g_bFlying[client] = true;
							War3_SetBuff(client, bFlyMode, thisRaceID, true);
						}
						else
						{
							if (g_bFlying[client])
							{
								g_bFlying[client] = false;
								War3_SetBuff(client, bFlyMode, thisRaceID, false);
								PrintHintText(client, "%t", "Ride Bat and fly!");
							}
							else
							{
								g_bFlying[client] = true;
								War3_SetBuff(client, bFlyMode, thisRaceID, true);
								PrintHintText(client, "%t", "Get off of bat and stop flying!");
							}
							War3_CooldownMGR(client, g_fUltCooldown, thisRaceID, ULT_CONCOCTION, _, false);
						}
					}
				}
			}
			else
			{
				W3MsgUltNotLeveled(client);
			}
		}
		else if (g_bFlyingType)
		{
			if (g_bFlying[client])
			{
				g_bFlying[client] = false;
				War3_SetBuff(client, bFlyMode, thisRaceID, false);
				War3_CooldownMGR(client, g_fUltCooldown, thisRaceID, ULT_CONCOCTION, _, false);
			}
		}
	}
}

public OnConVarChange(Handle:convar_hndl, const String:oldValue[], const String:newValue[])
{
	GetConVars();
}

public OnConfigsExecuted()
{
	GetConVars();
}

public GetConVars()
{
	g_fUltCooldown = GetConVarFloat(g_hCvarUltCooldown);
	g_bFlyingType = GetConVarBool(g_hCvarFlyingType);
	g_bCustomModel = GetConVarBool(g_hCvarCustomModel);
	g_iAmountOfGrenades = GetConVarInt(g_hCvarAmountOfGrenades);
}
